package com.googlecode.linkmein.repository;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.config.Configuration;
import com.db4o.query.Predicate;
import com.db4o.reflect.jdk.JdkReflector;
import com.googlecode.linkmein.domain.MapInfo;
import com.googlecode.linkmein.domain.MapInfoes;
import com.googlecode.linkmein.domain.revision.Change;
import com.googlecode.linkmein.domain.revision.NewProjectChange;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import java.util.ArrayList;
import java.util.List;

public class ObjectStorage implements DisposableBean, InitializingBean {
    private static final String DB_FILE = "linkmein.db";
    private Configuration config;
    private ObjectContainer db;

    public ObjectStorage() {
        config = Db4o.newConfiguration();
        config.reflectWith(new JdkReflector(this.getClass().getClassLoader()));
    }

    public void destroy() throws Exception {
        db.close();
    }

    public void afterPropertiesSet() throws Exception {
        db = Db4o.openFile(config, DB_FILE);
    }

    public void store(Change o) {                                                                    
        db.store(o);
    }

    public void store(List changes) {
        for (Object change : changes) {
            db.store(change);
        }
    }

    public List<Change> findAllChanges(int resultNumber) {
        ArrayList<Change> changes = new ArrayList<Change>();
        ObjectSet<Object> objects = db.queryByExample(Change.class);
        for (Object object : objects) {
            changes.add(((Change) object));
        }
        if (resultNumber <= 0 || changes.size() <= resultNumber) {
            return changes;
        } else {
            return changes.subList(0, resultNumber - 1);
        }
    }

    public NewProjectChange findNewProjectChangeByName(final String name) {
        List<NewProjectChange> changes = db.query(new Predicate<NewProjectChange>() {
            public boolean match(NewProjectChange change) {
                return change.getProject().getName().equals(name);
            }
        });
        if (changes.size() > 0) {
            return changes.get(0);
        } else {
            return null;
        }

    }

    public MapInfoes findAllMapInfoes() {
        MapInfoes mapInfoes = new MapInfoes();
        ObjectSet<MapInfo> foundMapInfoes = db.queryByExample(MapInfo.class);
        for (MapInfo mapInfo : foundMapInfoes) {
            mapInfoes.add(mapInfo);
        }
        return mapInfoes;
    }

    public void store(MapInfo mapInfo) {
        ObjectSet<MapInfo> foundMapInfoes = db.queryByExample(new MapInfo(0, 0, null, mapInfo.getShrinkedEnglishName(), mapInfo.getType().toString()));
        if (foundMapInfoes.size() != 0) {
            MapInfo foundInfo = foundMapInfoes.get(0);
            foundInfo.clone(mapInfo);
            db.store(foundInfo);
        } else {
            db.store(mapInfo);
        }
    }


}
